package util;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;



public class DHGenerator {

	/**
	 * @param args
	 */
	public static BigInteger findPrime() {
		//Generate prime where bit length 2^b 2<=b<=31
		
		SecureRandom rnd = new SecureRandom();
		int p = -1;
		BigInteger pbig;
		do{
		int blength = rnd.nextInt(20);
		if(blength <3)
		{
			blength +=3;
		}
		pbig = BigInteger.probablePrime(blength, rnd);
		p = pbig.intValue();
		}
		while(!MillerRabin32.miller_rabin_32(p)); // Protect against the 2^-100 chance of a non-prime
		
		return pbig;
		
		//System.out.println(findGenerator(new BigInteger(Integer.toString(p))).intValue());
		
	}
	
	public static BigInteger findGenerator(BigInteger prime){
		//Go through all the numbers 1 - p, exclusive on p; ensure that
		//g^n mod p maps to a value 1-p exclusive on p and all values in range
		//1-p exclusive are covered.  
	
		boolean goodg = false;
		int possibleg = 5;
		while(!goodg)
		{
			boolean flag = true;
			do{
				possibleg +=1;
				if(isGenerator(possibleg, prime.intValue())){
					flag = false;
					if(prime.intValue() > possibleg)
						goodg = true;
				}
				
			}while(flag);
			if(!goodg)
				possibleg = 0;
		}
		return new BigInteger(Integer.toString(possibleg));
	}
	
	public static boolean isGenerator(int g, int p){
		HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
		
		for(int n = 1; n<p; n++){
			map.put(n, MillerRabin32.modular_exponent_32(g, n, p));
		}
		
		Collection<Integer> values = map.values();
		Integer[] valueArr = new Integer[0];
		valueArr = values.toArray(valueArr);
		Set<Integer> keys = map.keySet();
		
		for(Integer i : valueArr){
			keys.remove(i);
		}
		
		if(keys.size() > 0)
			return false;
		return true;
	}

}
